package lib
import (
	"crypto/md5"
	"encoding/hex"
	"strconv"
	"github.com/astaxie/beego/httplib"
	"fmt"
	"encoding/xml"
	"time"
	"math/rand"
	"math"
	"strings"
)

//创建md5加密后的字符串
//@param s  string   输入要加密的字符串
//@return rs  string   返回加密的后字符串
func Strtomd5(s string) string {
	h := md5.New()
	h.Write([]byte(s))
	rs := hex.EncodeToString(h.Sum(nil))
	return rs
}

//给密码进行md5加密
//@param str  string   输入要加密的字符串
//@return rs  string   返回加密的后字符串
func Pwdhash(str string) string {
	return Strtomd5(str)
}

//将string转换成json
//@param str  string   输入要转换的字符串
//@return rs  string   返回加密的后字符串
func StringsToJson(str string) string {
	rs := []rune(str)
	jsons := ""
	for _, r := range rs {
		rint := int(r)
		if rint < 128 {
			jsons += string(r)
		} else {
			jsons += "\\u" + strconv.FormatInt(int64(rint), 16) // json
		}
	}

	return jsons
}
//发送帐号认证的验证码
//@param string  string   发送的内容
//@param tel  string      要发送的电话号码
func VerificationCode(content string,tel string)(bool){
	req:=httplib.Post("http://106.ihuyi.cn/webservice/sms.php?method=Submit")

	req.Param("account","cf_jhxu")
	req.Param("password","xujianhua15959")
	req.Param("mobile",tel)
	req.Param("content",content)
	//req.SetTimeout(100 * time.Second, 30 * time.Second).Response()
	str, err := req.String()
	if err != nil {
		fmt.Println("error",err)
	}
	fmt.Println("str",str)
	var tel_xml TelXML
	err = xml.Unmarshal([]byte(str), &tel_xml)
	if err != nil{
		return false
	}
	if tel_xml.Code == 2{
		//fmt.Println(tel_xml)
		return true
	}else{
		return false
	}


}

//产生指定范围的随机数
//@param min  int      最小值
//@param max  int      最大值范围
//@return   int        返回产生的随机数
func RandInt(min int , max int) int {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	return min + r.Intn(max-min)
}


//设备内存session
//@param key  interface      键
//@param value  int      	 值
func SetSelfSession(key string,value interface {}){
	SelfSession["key"+key] = value
}

//获取内存session
//@param key  interface      键
//@return   interface      	 返回键对应的值
func GetSelfSession(key string)(interface {}){
	return SelfSession["key"+key]
}

//初始化内存session
func init() {
	SelfSession = make(map[interface {}] interface {})
}
func AddMobileSession(user_id string,IP string){

	userSession := UserSessionType{LastDate:time.Now(),Count:0,VefifyCode:0,IP:IP,Encryptionkey:Strtomd5(strconv.FormatInt(int64(RandInt(100000,999999)), 10))}
	SetSelfSession(user_id,userSession)
}
func BootAnalyse(boot string)(bit_flow string,err error){

	string_array := strings.Split(boot, ",")      //将boot，以“，”为分割，分割成string数组
	var high_statistics map[string] int				//定义键值对，用于存储高电平数组
	high_statistics = make(map[string] int)			//创建键值对
	var low_statistics map[string] int				//定义键值对，用于存储低电平数组
	low_statistics = make(map[string] int)			//创建键值对
	str_len := len(string_array)					//计算长度
	int_array := make([]int, str_len)				//创建int型数组
	for i, v := range string_array {				//将string的值转换成int
		int_array[i], err = strconv.Atoi(v)
	}
	for i, v := range int_array {
		var power int
		bit_len := len(string_array[i])    //获取数据的位数，如4500，为4位
		//fmt.Println("bit_len",bit_len)
		power = int(math.Pow10(bit_len - 2))			//计算除数，如4500，除数为10^(4-2)
		//fmt.Println("power",power)
		unit := v % power								//取余
		if unit > (5*power/10) {						//如果数组大于5*power/10，则5入
			int_array[i] = v-unit+power
		}else {
			int_array[i] = v-unit						//如果数组小于5*power/10，则4舍入
		}
	}
	//fmt.Println("int_array", int_array)
	for i, v := range int_array {
		str_v := strconv.Itoa(v)					//将int转换成string，用于map的搜索
		if i%2 == 0 {								//偶数位，代表高电平
			count, ok := high_statistics[str_v]			//查询存高电平的数组，是否存在该键
			if !ok {
				high_statistics[str_v] = 0				//如果不存在，将计数值设为0
			}
			high_statistics[str_v] = count+1			//如果存在则加1

		}else {											//基数位代表低电平
			count, ok := low_statistics[str_v]
			if !ok {
				low_statistics[str_v] = 0
			}
			low_statistics[str_v] = count+1
		}
	}
//	fmt.Println("low_statistics", low_statistics)
//	fmt.Println("high_statistics", high_statistics)
	for k, v := range high_statistics {
		if float32(v)/float32(str_len) < 0.05 {					//计算高电平数组每个数据所出现的频率，小于5%的数据删除
			delete(high_statistics, k)
		}
	}
	for k, v := range low_statistics {							//计算低电平数组每个数组所出现的频率，小于5%的数据删除
		if float32(v)/float32(str_len) < 0.05 {
			delete(low_statistics, k)
		}
	}
	low_keys := make([]int, len(low_statistics))				//创建数组
	high_keys := make([]int, len(high_statistics))				//创建数组
	i := 0
	for k, _ := range low_statistics {				//将高电平的键值对中的键取出
		low_keys[i], _ = strconv.Atoi(k)
		i++
	}
	i = 0
	for k, _ := range high_statistics {				//将低电平的键值对中的键取出
		high_keys[i], _ = strconv.Atoi(k)
		i++
	}
	//fmt.Println("high_keys", high_keys)
	//fmt.Println("low_keys", low_keys)
	for i, k := range low_keys {				//将取回的低电平的值排序，从小到大
		for i_, k_ := range low_keys {
			if k < k_ {
				tmp := low_keys[i_]
				low_keys[i_] = low_keys[i]
				low_keys[i] = tmp
			}
		}
	}
	for i, k := range high_keys {			//将取回的高电平的值排序，从小到大
		for i_, k_ := range high_keys {
			if k < k_ {
				tmp := high_keys[i_]
				high_keys[i_] = high_keys[i]
				high_keys[i] = tmp
			}
		}
	}
	var optimal_low int
	var optimal_high int
	//取中位数，当做最优数据
	if len(low_keys)%2 == 0 {								//如果有取回有效的低电平的数量为偶数，取中间两个数的平均或者取最小的数
		key1 := float32(low_keys[len(low_keys) / 2 - 1])
		key2 := float32(low_keys[len(low_keys) / 2])

		if key2/key1 > 2.0 {										//大的数大于小的数的2倍，取小的数
			optimal_low = int(key1)
		}else {   //没有大于两倍，取两个数的加权平均
			optimal_low = int(math.Floor((float64(key1) + float64(key2)) / 2))
		}
	}else {													//如果为寄数，取中位数
//		key1 := float32(low_keys[(len(low_keys)-1)/ 2 - 1])   //中位数
//		key2 := float32(low_keys[(len(low_keys)-1)/ 2 - 2])		//中位数的上一位
//
//		if key1/key2 > 2.0 {										//大的数大于小的数的2倍，取小的数
//			optimal_low = int(key2)
//		}else {   //没有大于两倍，取两个数的平均
//			optimal_low = int(math.Floor((float64(key1) + float64(key2)) / 2))
//		}
		optimal_low = low_keys[(len(low_keys)-1)/2]
	}
	//取中位数，当做最优数据
	if len(high_keys)%2 == 0 {
		key1 := float32(high_keys[len(high_keys) / 2 - 1])
		key2 := float32(high_keys[len(high_keys) / 2])

		if key2/key1 > 2.0 {
			optimal_high = int(key1)
		}else {
			optimal_high = int(math.Floor(float64(key1) + float64(key2) / 2))
		}
	}else {
		//optimal_high = high_keys[(len(high_keys)-1)/2]
//		key1 := float32(high_keys[(len(high_keys)-1)/ 2 - 1])   //中位数
//		key2 := float32(high_keys[(len(high_keys)-1)/ 2 - 2])		//中位数的上一位
//
//		if key1/key2 > 2.0 {										//大的数大于小的数的2倍，取小的数
//			optimal_high = int(key2)
//		}else {   //没有大于两倍，取两个数的平均
//			optimal_high = int(math.Floor((float64(key1) + float64(key2)) / 2))
//		}
		optimal_high = high_keys[(len(high_keys)-1)/2]
	}
	var multiple float32
	if optimal_high > optimal_low {     //将取回最优数据，将大的除以小的
		multiple = float32(optimal_high)/float32(optimal_low)+1
	}else {
		multiple = float32(optimal_low)/float32(optimal_high)+1
	}
	if multiple < 3 {					//倍数小于3的都，都当2
		multiple = 2
	}
	average := int(optimal_high + optimal_low) / int(multiple)  //取平均
	bit_flow = ""
	over_turn := 0
	for i, k := range int_array{    //将数据转换成bit留，如average = 450，k=4500,bti_flow += "1111111111"
		if i%2 == 0 {
			over_turn = 1
		}else {
			over_turn = 0
		}


		unit := int(math.Floor(float64(k) / float64(average)+0.5))
		//fmt.Println("unit",unit,"k",k,"float",float32(k) / float32(average),"int",int(float32(k) / float32(average)))
		for j := 0; j < unit; j++ {
			if over_turn == 0 {
				bit_flow += "0"
			}else {
				bit_flow += "1"
			}
		}

	}
	//fmt.Println("bit_flow",bit_flow)
	return bit_flow,err
}


